// Branch.m -- major constituent of tree

#import "Branch.h"
#import "Tree.h"
#import "ForestCamera.h"
#import <ri/ri.h>
#import <math.h>

@implementation Branch:N3DShape

id globalShader;
- tree :treeArg	{tree = treeArg;  return self;}

- addBranches :(int)level inTree :treeArg
{	Branch *aBranch, *firstBranch=0;
	Tree *myTree = tree;
	RtPoint xAxis = {1.0, 0.0, 0.0};
	RtPoint zAxis = {0.0, 0.0, 1.0};
	int i, bf = [myTree randVal :BRANCHFACTOR];	// number of branches
	float twi = [myTree randVal :TWIST];
	
	if (level >= (i=[myTree randVal :LEVELS]))
		return self;
		
	for (i=0; i<bf; i++)
	{	float shr = [myTree randVal :SHRINK];
		float ang = [myTree randVal :ANGLE];
		float tra = 0.90;						// translation
		static float k = 2.0*M_PI/360.0;
		float x0=0.0, y0=0.0, z0=tra, x1, y1, z1;

		aBranch = [[Branch alloc] init];
		if (i == 0)
			[self linkDescendant :firstBranch=aBranch];
		else
			[firstBranch linkPeer :aBranch];
		[aBranch tree :treeArg];
		[aBranch setShader :globalShader];
		[aBranch rotateAngle :ang axis :xAxis];
		[aBranch rotateAngle :twi + 360.0*i/bf axis :zAxis];
		[aBranch scaleUniformly :shr];
		[aBranch translate :0.0 :0.0 :tra];

		if ((x1 = shr*sin(ang*k)*sin(twi*k)) < 0)	{	x0 = x1; x1 = 0.0;}
		if ((y1 = shr*sin(ang*k)*cos(twi*k)) < 0)	{	y0 = y1; y1 = 0.0;}
		if ((z1 = tra + shr*cos(ang*k)) < tra)		{	z0 = z1; z1 = tra;}
		[aBranch setBoundingBox :x0 :x1 :y0 :y1 :z0 :z1];
		[aBranch addBranches :level+1 inTree :treeArg];
	}
	return self;
}

- setBoundingBox :(float)xMin :(float)xMax :(float)yMin :(float)yMax 
												:(float)zMin :(float)zMax
{	boundingBox[0] = xMin;
	boundingBox[1] = xMax;
	boundingBox[2] = yMin;
	boundingBox[3] = yMax;
	boundingBox[4] = zMin;
	boundingBox[5] = zMax;
	return self;
}

- renderSelf:(RtToken)context
{	RiCylinder( .1, .1, 1, 360, RI_NULL);
	return self;
}

@end
  
